package com.gezi.admin.config.argument;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.gezi.admin.config.exception.type.ParamException;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Type;
import java.util.Map;

/**
 * @Author 格子代码
 * @createDate 2024/2/10 09:00
 * @contact 1424529270@qq.com
 */
@Component
public class MyHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
    @Override
    public boolean supportsParameter(MethodParameter methodParameter) {
        return methodParameter.hasParameterAnnotation(RequestBodyParam.class);
    }

    @Override
    public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
        if(methodParameter.hasParameterAnnotation(RequestBodyParam.class)){
            RequestBodyParam requestBodyParam = methodParameter.getParameterAnnotation(RequestBodyParam.class);
            String fieldName = methodParameter.getParameterAnnotation(RequestBodyParam.class).value();
            if(StrUtil.isBlank(fieldName)){
                fieldName = methodParameter.getParameter().getName();
            }

            HttpServletRequest servletRequest = (HttpServletRequest)nativeWebRequest.getNativeRequest(HttpServletRequest.class);

            SafeHttpServletRequestWrapper requestWrapper = new SafeHttpServletRequestWrapper((HttpServletRequest) servletRequest);
            Map<String,Object> map = JSON.parseObject(requestWrapper.getBodyString(),Map.class);
            if(map == null){
                map = (Map<String, Object>) servletRequest.getAttribute("requestBodyParamData");
                if(map == null){
                    return servletRequest.getParameter(fieldName);
                }
                if(map.containsKey(fieldName)){
                    Object value = map.get(fieldName);
                    if(requestBodyParam.required() && ObjectUtil.isEmpty(value)){
                        throw ParamException.getInstance("必填项不能为空");
                    }

                    Type type = methodParameter.getParameter().getType();
                    if(((Class) type).isPrimitive()){
                        return value;
                    }else if(((Class)type).isArray()){
                        return JSON.parseObject(value.toString(),type);
                    }else{
                        if(type.getTypeName().equals(String.class.getTypeName())){
                            return value;
                        }else if(type.getTypeName().equals(Byte.class.getTypeName())){
                            return value;
                        }else if(type.getTypeName().equals(Short.class.getTypeName())){
                            return value;
                        }else if(type.getTypeName().equals(Integer.class.getTypeName())){
                            return value;
                        }else if(type.getTypeName().equals(Long.class.getTypeName())){
                            return value;
                        }else if(type.getTypeName().equals(Float.class.getTypeName())){
                            return value;
                        }else if(type.getTypeName().equals(Double.class.getTypeName())){
                            return value;
                        }else if(type.getTypeName().equals(Character.class.getTypeName())){
                            return value;
                        }else if(type.getTypeName().equals(Boolean.class.getTypeName())){
                            return value;
                        }else{
                            return JSON.parseObject(((JSONObject)value).toJSONString(),type);
                        }
                    }

                }else{
                    if(requestBodyParam.required()){
                        throw ParamException.getInstance("必填项不能为空");
                    }
                }
            }else{
                servletRequest.setAttribute("requestBodyParamData",map);

                if(map.containsKey(fieldName)){
                    Object value = map.get(fieldName);
                    if(requestBodyParam.required() && ObjectUtil.isEmpty(value)){
                        throw ParamException.getInstance("必填项不能为空");
                    }
                    return value;
                }else{
                    if(requestBodyParam.required()){
                        throw ParamException.getInstance("必填项不能为空");
                    }
                }
            }
        }
        return null;
    }
}
